// 【文件相关】
import { basename } from 'path'
import {
  loadJson,
  assert,
  sleep,
  ROOT,
  genMutations,
  notify,
  showMsg,
  showAsk,
  appCall,
  dlgPost,
  utilPost
} from 'boot/utils'
import { JSON_FILE_FILTERS } from 'boot/filefilters'

// ----------------------------------------------------------------------------【state】
const state = () => ({
  filePath: '', // 当前打开的文件路径
  lastFilePath: '', // 上次打开或保存的文件路径
  modified: false // 上次保存后是否有修改
})

// ----------------------------------------------------------------------------【getters】
const getters = {
  // 当前文档标题
  docTitle (state) {
    return basename(state.filePath) || '<未命名>'
  }
}

// ----------------------------------------------------------------------------【mutations】
const mutations = {
  ...genMutations([
    'filePath',
    'lastFilePath',
    'modified'
  ])
}

// ----------------------------------------------------------------------------【actions】
const actions = {
  // 新建
  async create ({ commit, dispatch }) {
    if (await dispatch('saveAsk')) return
    await dispatch('edit/reset', null, ROOT)
    commit('filePath', '')
  },

  // 打开
  async open ({ state, rootGetters, commit, dispatch }) {
    const { canceled = true, filePaths } =
      (await dlgPost('showOpenDialog', {
        title: '打开',
        filters: JSON_FILE_FILTERS,
        defaultPath: state.filePath || state.lastFilePath
      })) || {}
    if (canceled) return
    const filePath = filePaths[0]

    // 加载数据
    let data
    try {
      data = await loadJson(filePath)
      assert(data != null, '无法加载文件！')
      assert(rootGetters['edit/verify'](data), '数据格式错误！')
    } catch (e) {
      return showMsg('读取数据失败！<br>' + e.message)
    }

    if (await dispatch('reset', data)) {
      commit('filePath', filePath)
      commit('lastFilePath', filePath)
    }
  },

  // 重置
  // - @info 内容信息
  // - @return 是否成功
  async reset ({ commit, dispatch }, info) {
    if (await dispatch('saveAsk')) return false
    commit('main/loading', '正在载入数据，请稍候...', ROOT)
    await sleep(100)
    await dispatch('edit/reset', info, ROOT)
    commit('main/loading', false, ROOT)
    commit('filePath', '')
    return true
  },

  // 保存
  // - @filePath 指定保存的文件路径
  // - @return 是否成功（null表示取消）
  async save ({ state, rootState, rootGetters, commit, dispatch }, filePath) {
    filePath = filePath || state.filePath
    if (!filePath) {
      return await dispatch('saveAs')
    }

    // 保存数据
    const data = rootGetters['edit/dataJson'](0)
    const success = await utilPost('saveFile', filePath, data)
    if (!success) {
      showMsg('保存失败！')
      return false
    }
    commit('filePath', filePath)
    commit('lastFilePath', filePath)
    commit('modified', false)
    notify('保存成功')

    // 记录保存时的当前操作
    const oper = rootState.edit.undoStack[rootState.edit.undoStack.length - 1]
    commit('edit/savedOper', oper, ROOT)
    return true
  },

  // 另存为
  // - @return 是否成功（null表示取消）
  async saveAs ({ state, dispatch }) {
    const { canceled = true, filePath } =
      (await dlgPost('showSaveDialog', {
        title: '另存为',
        filters: JSON_FILE_FILTERS,
        defaultPath: state.filePath || state.lastFilePath
      })) || {}
    if (canceled) return null
    return await dispatch('save', filePath)
  },

  // 提示保存修改
  // - @return 是否取消
  async saveAsk ({ state, dispatch }) {
    if (state.modified) {
      const answer = await showAsk('当前有修改内容尚未保存，是否要保存？')
      if (answer === null) return true
      if (answer && !(await dispatch('save'))) return true
    }
    return false
  },

  // 尝试退出（会提示是否要保存）
  async tryQuit ({ state, dispatch }) {
    if (state.modified) {
      if (await dispatch('saveAsk')) return
    }
    appCall('exit')
  }
}

export default {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
}
